﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using GameSchoolApplication.Models;
using GameSchoolApplication.Models.ViewModels;

namespace GameSchoolApplication.Repositories
{
    public class SubmissionRepository
    {
        gsDBDataContext link = new gsDBDataContext();

        /// <summary>
        /// Gets submission based on ID
        /// Precondition: submissionID must exist
        /// Postcondition: a submission is returned
        /// Author: Bjarmi mod. by Alma
        /// Date: 07.05. 2012
        /// </summary>
        public Submission getSubmissionByID(int submID)
        {
            Submission selectedSubmission = (from s in link.Submissions
                               where s.submissionID == submID
                               select s).First();            
            return selectedSubmission; 
        }

        /// <summary>
        /// Gets submissions based on userID
        /// Precondition: User must exist
        /// Postcondition: A list of a users submissions is returned
        /// Author: Aron mod. by Alma
        /// Date: 07.05. 2012
        /// </summary>
        public IQueryable <Submission> getUserSubmissions(string userID)
        {
            IQueryable<Submission> subm = (from s in link.Submissions
                                           from u in link.StudentSubmissions
                                           where s.submissionID == u.submissionID && u.studentID == userID
                                           select s);
            return subm;
        }

        
        /// <summary>
        /// Gets a list of submissions
        /// Precondition:
        /// Postcondition: A list of all submissions is returned
        /// Author: Aron/Bjarmi mod. by Alma
        /// Date: 07.05. 2012
        /// </summary>
        public IQueryable<Submission> getAllSubmissions()
        {
            return link.Submissions;
        }

        /// <summary>
        /// TODO: Write a cool-ass description!
        /// As of right now this is just a dummy class 
        /// Precondition:
        /// Postcondition:
        /// Author:
        /// Date: 07.05. 2012
        /// </summary>
        public int addSubmission(Submission mission)
        {
            try
            {
                link.Submissions.InsertOnSubmit(mission);
                save();
            }
            catch (Exception)
            {
                return 0;
            }
            return mission.submissionID; 
        }

        /// <summary>
        /// Editing Submissions
        /// Precondition: User must be an administrator and the submission must exist
        /// Postcondition: Submission information have been updated
        /// Author: Aron Mar mod. by Alma
        /// Date: 07.05. 2012
        /// </summary>
        public bool editSubmission(Submission mission)
        {
            try
            {
                var subm = (from s in link.Submissions
                            where s.submissionID == mission.submissionID
                            select s).First();

                subm.studentComment = mission.studentComment;
                subm.teacherFeedback = mission.teacherFeedback;
                subm.dateOfSubmission = mission.dateOfSubmission;
                subm.grade = mission.grade;

                save();

                return true;
            }
            catch (Exception)
            {
                return false;
            }
            
        }

        /// <summary>
        /// gets all assignments for a specified user.
        /// 
        /// </summary>
        /// <param name="userID">userID</param>
        /// <returns>IEnumerable of all assignments the user has access to</returns>
        public IEnumerable<Assignment> getUserAssList(string userID)
        {
            var assList = from S in link.Submissions
                          from StS in link.StudentSubmissions
                          from A in link.Assignments
                          where S.submissionID == StS.submissionID && userID == StS.studentID && S.assignmentID == A.assignmentID
                          select A;
            return assList.AsEnumerable();
        }

        /// <summary>
        /// Fetches Assignment, its grade(if it has one) and what course it belongs to...
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public SortedList<string,List<assWithGrade>> getUserAssGrades(string userID)
        {
            var assGradeList = from S in link.Submissions
                          from StS in link.StudentSubmissions
                          from A in link.Assignments
                          where S.submissionID == StS.submissionID && userID == StS.studentID && S.assignmentID == A.assignmentID
                          select new assWithGrade { ass = A, grade = (S.grade.HasValue ? S.grade.Value : -1), coursename = (from c in link.Courses
                                                                                                                            where c.cID == (from l in link.CourseLevels
                                                                                                                                            where A.lvlID==l.lvlID
                                                                                                                                            select l.cID).First()
                                                                                                                            select c.name).First()};
            SortedAsses assSort = new SortedAsses();
            assSort.data = new SortedList<string, List<assWithGrade>>();
            foreach (var ass in assGradeList)
            {
                if (!assSort.data.Keys.Contains(ass.coursename))
                    assSort.data.Add(ass.coursename, new List<assWithGrade>());
                assSort.data[ass.coursename].Add(ass);
            }

            return assSort.data;
        }

        /// <summary>
        /// Inserts a single file entry for a submission into the db
        /// precondition:the submission must exist in the database
        /// postcondition:a file is now referenced in the database
        /// Author:Bjarmi
        /// </summary>
        /// <param name="submissionID"></param>
        /// <param name="filePath"></param>
        /// <param name="fileSize"></param>
        /// <returns></returns>
        public bool addFileForSubmission(int submissionID, string filePath, int fileSize)
        {
            FilesForSubmission temp = new FilesForSubmission();
            temp.submissionID = submissionID;
            temp.fname = filePath;
            temp.fsize = fileSize;

            try
            {
                link.FilesForSubmissions.InsertOnSubmit(temp);
                save();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Returns all of the FilesForSubmission for a submission. 
        /// Postcondition: A IQueryable of all of the FileForSubmission objects is returned.
        /// Author: Krilli
        /// Date: 9.5
        /// </summary>
        /// <param name="submissionID">The ID of the submission</param>
        /// <returns>A container containing all of the submitted file objects</returns>
        public IQueryable<FilesForSubmission> getFilesForSubmission(int submissionID)
        {
            IQueryable<FilesForSubmission> subs = (from s in link.FilesForSubmissions
                                                   where s.submissionID == submissionID
                                                   select s);
            return subs; 
        }

        /// <summary>
        /// Returns all of the Submissions for a assignment. 
        /// Postcondition: A IQueryable of all of the Submission objects for the assignment is returned.
        /// Author: Krilli
        /// Date: 9.5
        /// </summary>
        /// <param name="assignmentID">The ID of the assignment</param>
        /// <returns>A container containing all of the submit objects</returns>
        public IQueryable<Submission> getSubmissionsForAssignment(int assignmentID)
        {
            IQueryable<Submission> subs = (from s in link.Submissions
                                           where s.assignmentID == assignmentID
                                           select s);
            return subs; 
        }

        /// <summary>
        /// Saves changes to database
        /// Precondition:
        /// Postcondition: Database has been updated
        /// Author: Aron og Bjarmi
        /// Date: 03.05.2012
        /// </summary>
        public void save()
        {
            link.SubmitChanges();
        }

        /// <summary>
        /// Adds a student submission to the database.
        /// Postcondition: The student submission has been added to the StudentSubmissions table
        /// Author: krilli
        /// Date: 9.5
        /// </summary>
        /// <param name="submissionID"></param>
        /// <param name="studentID"></param>
        /// <returns></returns>
        public bool addStudentSubmission(int submissionID, string studentID)
        {
            StudentSubmission sSubmission = new StudentSubmission();
            sSubmission.submissionID = submissionID;
            sSubmission.studentID = studentID;
            try
            {
                link.StudentSubmissions.InsertOnSubmit(sSubmission);
                save(); 
            }
            catch (Exception)
            {
                return (false);
            }
            return true; 
        }

        /// <summary>
        /// Adds a new file for submission.
        /// Postcondition: A new entry in the file for submission table is created.
        /// Author: Krilli
        /// Date: 9.5 
        /// </summary>
        /// <param name="submissionID"></param>
        /// <param name="fname"></param>
        /// <returns></returns>
        public bool addFileForSubmission(int submissionID, string fname)
        {
            FilesForSubmission fSub = new FilesForSubmission();
            fSub.submissionID = submissionID;
            fSub.fname = fname;
            fSub.fsize = 1; 
            try
            {
                link.FilesForSubmissions.InsertOnSubmit(fSub);
                save(); 
                return true;
            }
            catch (Exception)
            {
                return false;
            }
            
        }

        public Dictionary<string, int> getSubmissionsOfAssignment(int assID)
        {
            Dictionary<string, int> list = new Dictionary<string, int>();

            var result = (from sub in link.StudentSubmissions
                          from s in link.Submissions
                          where s.assignmentID == assID && s.submissionID == sub.submissionID
                          select sub);

            foreach (StudentSubmission r in result)
            {
                list.Add(r.studentID, r.submissionID);
            }
            
            return list;
        }

    }
}

/*public IQueryable<Submission> getSubmissionsByAssignment(int assignmentID)
        {
            IQueryable<Submission> selectedSubmissions = (from s in link.Submissions
                                                          where s.assignmentID == assignmentID
                                                          select s);
            return selectedSubmissions;
        }

        public StudentSubmission getStudentSubmissionsBySubmission(int submissionID)
        {
            StudentSubmission selectedSSubmission = (from s in link.StudentSubmissions
                                                                  where s.submissionID == submissionID
                                                                  select s).First();
            return selectedSSubmission;
        }*/